package io.github.uicdb.et;

import io.github.uicdb.et.block.ElementMachineBlockEntity;
import io.github.uicdb.et.block.ExtractMachineBlockEntity;
import io.github.uicdb.et.block.ICraft;
import io.github.uicdb.et.block.TurnInBlockEntity;
import io.github.uicdb.et.capability.ElementalAsFluid;
import io.github.uicdb.et.capability.IElementalHandler;
import io.github.uicdb.et.capability.ModCapability;
import io.github.uicdb.et.item.curios.CurioItem;
import io.github.uicdb.et.item_data.ItemElementData;
import io.github.uicdb.et.net.CCraftInPosPayload;
import io.github.uicdb.et.register.ElementalObject;
import io.github.uicdb.et.register.RegisterHelper;
import net.minecraft.core.Direction;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.item.*;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.capabilities.Capabilities;
import net.neoforged.neoforge.capabilities.ICapabilityProvider;
import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent;
import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent;
import net.neoforged.neoforge.fluids.capability.IFluidHandler;
import net.neoforged.neoforge.items.IItemHandler;
import net.neoforged.neoforge.items.wrapper.InvWrapper;
import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.List;

import static io.github.uicdb.et.ElementalTheory.*;

public class ModEventHandle {
    public static void handle(IEventBus modBus, IEventBus gameBus) {
        modBus.addListener(ModEventHandle::registerCreativeTab);
        modBus.addListener(ModEventHandle::registerNetwork);
        modBus.addListener(ModEventHandle::registerCapabilties);
    }

    private static void registerCapabilties(RegisterCapabilitiesEvent event) {
        event.registerBlockEntity(Capabilities.FluidHandler.BLOCK, ModBlockEntityType.EXTRACT_MACHINE.get(), new ICapabilityProvider<>() {
            @Override
            public @NotNull IFluidHandler getCapability(@NotNull ExtractMachineBlockEntity o, Direction direction) {
                return new ElementalAsFluid(o.getElementalHandler());
            }
        });
        event.registerBlockEntity(Capabilities.ItemHandler.BLOCK, ModBlockEntityType.EXTRACT_MACHINE.get(), new ICapabilityProvider<>() {
            @Override
            public @NotNull IItemHandler getCapability(ExtractMachineBlockEntity o, Direction direction) {
                return new InvWrapper(o);
            }
        });
        event.registerBlockEntity(ModCapability.ElementalHandler.BLOCK, ModBlockEntityType.EXTRACT_MACHINE.get(), new ICapabilityProvider<>() {
            @Override
            public @NotNull IElementalHandler getCapability(ExtractMachineBlockEntity o, @Nullable Direction direction) {
                return o.getElementalHandler();
            }
        });
        event.registerBlockEntity(Capabilities.ItemHandler.BLOCK, ModBlockEntityType.ELEMENT_MACHINE.get(), new ICapabilityProvider<>() {
            @Override
            public @NotNull IItemHandler getCapability(ElementMachineBlockEntity o, @Nullable Direction direction) {
                return new InvWrapper(o);
            }
        });
        event.registerBlockEntity(Capabilities.FluidHandler.BLOCK, ModBlockEntityType.ELEMENT_MACHINE.get(), new ICapabilityProvider<>() {
            @Override
            public @NotNull IFluidHandler getCapability(@NotNull ElementMachineBlockEntity o, @Nullable Direction direction) {
                return new ElementalAsFluid(o.getElementalHandler());
            }
        });
        event.registerBlockEntity(ModCapability.ElementalHandler.BLOCK, ModBlockEntityType.ELEMENT_MACHINE.get(), new ICapabilityProvider<>() {
            @Override
            public @Nullable IElementalHandler getCapability(ElementMachineBlockEntity o, @Nullable Direction direction) {
                return o.getElementalHandler();
            }
        });
        event.registerBlockEntity(ModCapability.ElementalHandler.BLOCK, ModBlockEntityType.TURN_IN_MACHINE.get(), new ICapabilityProvider<>() {
            @Override
            public @Nullable IElementalHandler getCapability(TurnInBlockEntity o, @Nullable Direction direction) {
                return o.getElementalHandler();
            }
        });
    }

    private static void registerCreativeTab(BuildCreativeModeTabContentsEvent event) {

        if (event.getTab() == CREATIVE_MODE_TAB.get()) {
            BuiltInRegistries.BLOCK.entrySet().forEach(entry -> {
                var location = entry.getKey().location();
                var block = entry.getValue();
                if (location.getNamespace().equals(MODID))
                    event.accept(block);
            });
        }
        if (event.getTab() == CREATIVE_MODE_TAB_TOOL.get()) {
            BuiltInRegistries.ITEM.stream().filter(item -> item instanceof SwordItem).map(item -> (SwordItem) item)
                    .forEach(swordItem -> {
                        for (ElementalObject object : RegisterHelper.getElementalObjects()) {
                            ItemStack stack = new ItemStack(swordItem);
                            if (!stack.has(ModItemDataComponents.ITEM_ELEMENT_DATA)) {
                                stack.set(ModItemDataComponents.ITEM_ELEMENT_DATA, new ItemElementData(object.getElementHolder(), 3, 100));
                                event.accept(stack);
                            }
                        }
                    });
            for (ElementalObject object : RegisterHelper.getElementalObjects()) {
                var stack = new ItemStack(Items.SHIELD);
                if (!stack.has(ModItemDataComponents.ITEM_ELEMENT_DATA)) {
                    stack.set(ModItemDataComponents.ITEM_ELEMENT_DATA, new ItemElementData(
                            object.getElementHolder(), 2, 25
                    ));
                    event.accept(stack);
                }
            }
            event.accept(ModItems.WATER_SOURCE_STAFF);
            event.accept(ModItems.LIGHTNING_SWORD);
            event.accept(ModItems.SALAMANDRA);
            event.accept(ModItems.GUST);
            event.accept(ModItems.NIGHT_DEMON);
        }
        if (event.getTab() == CREATIVE_MODE_TAB_ARMOR.get()) {

        }
        if (event.getTab() == CREATIVE_MODE_TAB_CURIO.get()) {
            BuiltInRegistries.ITEM.stream().filter(item -> item instanceof CurioItem).map(item -> (CurioItem) item)
                    .forEach(event::accept);
        }
    }

    private static void registerNetwork(RegisterPayloadHandlersEvent event) {
        event.registrar("1.0")
                .playToServer(CCraftInPosPayload.TYPE, CCraftInPosPayload.STREAM_CODEC, (payload, context) -> {
                    var pos = payload.pos();
                    var be = context.player().level().getBlockEntity(pos);
                    if (be instanceof ICraft iCraft) iCraft.tirggerCraft();
                })
        ;
    }

    private static List<List<ElementalObject>> getObjectsForAllElement() {
        List<ElementalObject> objects = RegisterHelper.getElementalObjects();
        List<List<ElementalObject>> result = new ArrayList<>();
        int totalElements = objects.size();
        int totalCombinations = 1 << totalElements; // 2^n combinations (including empty set)

        for (int i = 0; i < totalCombinations; i++) {
            List<ElementalObject> combo1 = new ArrayList<>();
            for (int j = 0; j < totalElements; j++) {
                // Check if the jth bit is set
                if ((i & (1 << j)) != 0) {
                    combo1.add(objects.get(j));
                }
            }
            if (combo1.isEmpty()) continue;
            result.add(combo1);
        }

        return result;
    }
}
